<?php

namespace App\Console\Commands;

use App\Helper\ChatHelper;
use App\Helper\LogHelper;
use Illuminate\Console\Command;
use App\Base\CommonPoolMethod;
use App\Service\Doctor\DoctorService;
use Illuminate\Support\Facades\Redis;
use Modules\Chat\Models\ChatMessage;
use Modules\Chat\Models\ChatRoomJoin;
use Modules\Chat\Models\ChatUser;

class CommandSwoole extends Command
{
    use CommonPoolMethod;

    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'swoole:action {action}';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = 'swoole 启动、暂停、重启';

    /**
     * @var ChatMessage
     */
    protected $chatMessage;

    /**
     * @var ChatUser
     */
    protected $chatUser;

    /**
     * @var ChatRoomJoin
     */
    protected $chatRoomJoin;

    /**
     * CommandSwoole constructor.
     * @param ChatMessage $chatMessage
     * @param ChatUser $chatUser
     * @param ChatRoomJoin $chatRoomJoin
     */
    public function __construct(ChatMessage $chatMessage, ChatUser $chatUser, ChatRoomJoin $chatRoomJoin)
    {
        parent::__construct();
        $this->chatMessage = $chatMessage;
        $this->chatUser = $chatUser;
        $this->chatRoomJoin = $chatRoomJoin;
    }

    /**
     * Execute the console command.
     *
     * @return mixed
     */
    public function handle()
    {
        $action = $this->argument('action');
        LogHelper::info('handle action', $action);
        switch ($action) {
            case 'start':
                $this->start();
                break;
            case 'stop':
                $this->stop();
                break;
            case 'restart':
                $this->restart();
                break;
        }
    }

    /**
     * 开启websocket
     */
    private function start()
    {
        LogHelper::info('start', 'start');

        $ws = new \swoole_websocket_server(config('swoole.host'), config('swoole.port'));
        $ws->on('open', function ($ws, $request) {
            // todo something
        });

        LogHelper::info('start2', 'start2');

        //监听WebSocket消息事件
        $ws->on('message', function ($ws, $frame) {

            $data = json_decode($frame->data, true);

            LogHelper::info('ws', $ws);
            LogHelper::info('frame', $frame);
            LogHelper::info('data', $data);

            switch ($data['keytype']) {
                case 'connect':
                    Redis::zadd("laravel8_room:{$data['room_id']}", intval($data['user_id']), $frame->fd);
                    // 同时使用hash标识fd在哪个房间
                    Redis::hset('laravel8_room', $frame->fd, $data['room_id']);
                    // 加入房间提示
                    // 获取这个房间的用户总数
                    // +1 是代表群主
                    $memberInfo = [
                        'online' => Redis::zcard("laravel8_room:{$data['room_id']}"),
                        'all' => $this->room->where(['room_id' => $data['room_id'], 'status' => 0])->count() + 1
                    ];

                    $this->sendAll($ws, $data['room_id'], $data['user_id'], $memberInfo, 'join');
                    break;
                case 'message':
                    // 数据转成json
                    $contentData['content'] = $data['data'];
                    $content = json_encode($contentData);
                    // 入库
                    $message = [
                        'user_id'     => $data['user_id'],
                        'room_id'     => $data['room_id'],
                        'object_name' => ChatHelper::OBJECT_NAME['TxtMsg'],
                        'content'     => $content,
                        'created_at'  => time()
                    ];
                    // $this->message->fill($message)->save();
                    $chatMessage = ChatMessage::create($message);

                        $this->sendAll($ws, $data['room_id'], $data['user_id'], $chatMessage);
                    break;
                case 'close':
                    // 移除
                    Redis::zrem("laravel8_room:{$data['room_id']}", $frame->fd);

                    break;
            }

        });

        //监听WebSocket request 事件
        $ws->on('request', function ($request, $response) use ($ws) {

            LogHelper::info('request', $request);
            $data = $request->post['data'];  // 获取值
            $data = json_decode($data, true);

            LogHelper::info('ws', $ws);
            LogHelper::info('data', $data);

            switch ($data['keytype']) {
                case 'connect':

                    break;
                case 'message':
                    // 数据转成json
                    $contentData['content'] = $data['data'];
                    $content = json_encode($contentData);
                    // 入库
                    $message = [
                        'user_id'     => $data['user_id'],
                        'room_id'     => $data['room_id'],
                        'object_name' => $data['object_name'],
                        'content'     => $content,
                        'created_at'  => time()
                    ];
                    // $this->message->fill($message)->save();
                    $chatMessage = ChatMessage::create($message);

                    $this->sendAll($ws, $data['room_id'], $data['user_id'], $chatMessage);
                    break;
                case 'close':
                    // 移除
                    break;
            }

        });

        LogHelper::info('start3', 'start3');
        $ws->on('close', function ($ws, $fd) {
            // 获取fd所对应的房间号
            $room_id = Redis::hget('laravel8_room', $fd);
            $user_id = intval(Redis::zscore("laravel8_room:{$room_id}", $fd));
            Redis::zrem("laravel8_room:{$room_id}", $fd);

            $memberInfo = [
                'online' => Redis::zcard("laravel8_room:{$room_id}"),
                'all' => $this->room->where(['room_id' => $room_id, 'status' => 0])->count() + 1
            ];

//            $this->sendAll($ws, $room_id, $user_id, $memberInfo, 'leave');
        });

        $ws->start();
    }

    /**
     * 停止websocket
     */
    private function stop()
    {
        $ws = new \swoole_websocket_server(config('swoole.host'), config('swoole.port'));
        $ws->close();
    }

    /**
     * 重启
     */
    private function restart()
    {

    }

    /**
     * @param $ws
     * @param $room_id
     * @param null $user_id
     * @param null $chat_message
     * @param string $keytype
     * @return false
     */
    public function sendAll($ws, $room_id, $user_id = null, $chat_message = null, $keytype = 'message')
    {
        $user = $this->chatUser->find($user_id, ['id', 'nickname']);
        if (!$user) {
            return false;
        }

        // 消息体待定
        $message = json_encode([
            // 'message' => is_string($chat_message->content) ? nl2br($chat_message->content) : $chat_message->content,
            'content' => $chat_message->content,
            'keytype' => $keytype,
            'user' => $user,
            'uid' => $user->id,
            'guid' => $chat_message->id,
            'keytext' => is_string($chat_message->content) ? nl2br($chat_message->content) : $chat_message->content
        ]);
        $members = Redis::zrange("laravel8_room:{$room_id}" , 0 , -1);
        foreach ($members as $fd) {
            $ws->push($fd, $message);
        }
    }
}
